from glob import glob
from os import path
from setuptools import Extension, setup
from setuptools.command.install import install
from subprocess import check_output, CalledProcessError


ROOT_DIR = path.dirname(path.realpath(__file__))
MOD_DIR = path.join(ROOT_DIR, 'cpython')
SRC_DIR = path.join(ROOT_DIR, 'src')
CODEC_DIR = path.join(SRC_DIR, 'codec')
INCL_DIR = path.join(ROOT_DIR, 'include')
EXT_DIR = path.join(ROOT_DIR, 'ext')

LEXER = 're2c'
PARSER = 'lemon'


sources = (
    glob(path.join(SRC_DIR, '*.c')) +
    glob(path.join(CODEC_DIR, '*_grammar.c')) +
    glob(path.join(SRC_DIR, 'codec', '*_parser.c')) +
    glob(path.join(MOD_DIR, '*.c')) +
    [
        path.join(EXT_DIR, 'openldap', 'libraries', 'liblmdb', 'mdb.c'),
        path.join(EXT_DIR, 'openldap', 'libraries', 'liblmdb', 'midl.c'),
        path.join(EXT_DIR, 'xxHash', 'xxhash.c'),
        path.join(EXT_DIR, 'hashmap', 'hashmap.c'),
        path.join(EXT_DIR, 'tpl', 'src', 'tpl.c'),
        path.join(EXT_DIR, 'log', 'src', 'log.c'),
    ]
)

debug = True

compile_args = [
    '-DLOG_USE_COLOR',
    # '-std=c99',
]
if debug:
    compile_args.extend(['-DDEBUG', '-g3', '-O0'])
else:
    compile_args.extend(['-g0', '-O3'])


class LSUPInstallCmd(install):
    """
    Run LSUP-specific hooks in extension build phase.

    TODO Extending the Extension class may be best to narrow the scope to the
    C module.
    """

    def run(self):
        # Run grammar and parser generators.
        try:
            lexer_ex_path = check_output(['which', LEXER])
        except CalledProcessError:
            raise SystemError(f'Lexer program `{LEXER}` is not installed.')

        try:
            parser_ex_path = check_output(['which', PARSER])
        except CalledProcessError:
            raise SystemError(f'Lexer program `{PARSER}` is not installed.')

        print("Generating grammar.")
        for fpath in glob(path.join(CODEC_DIR, '*_grammar.y')):
            check_output([
                parser_ex_path, fpath, 'q', '-m',
                '-T' + fpath.join(CODEC_DIR, 'lempar.c'), f'-d{CODEC_DIR}'
            ])

        print("Generating parser.")
        for fpath in glob(path.join(CODEC_DIR, '*_lexer.re')):
            check_output([
                lexer_ex_path, fpath, '-o',
                fpath.replace('_lexer.re', '_parser.c'), '-T', '--case-ranges',
            ])

        install.run(self)


setup(
    name="lsup_rdf",
    version="1.0a2",
    description='Ultra-compact RDF library.',
    author='Stefano Cossu <https://notabug.org/scossu>',
    url='https://notabug.org/scossu/lsup_rdf',
    license='https://notabug.org/scossu/lsup_rdf/src/master/LICENSE',
    package_dir={'lsup_rdf': path.join(MOD_DIR, 'lsup_rdf')},
    packages=['lsup_rdf'],
    cmdclasss={'install': LSUPInstallCmd},
    ext_modules=[
        Extension(
            "_lsup_rdf",
            sources,
            include_dirs=[
                ROOT_DIR,
                INCL_DIR,
                path.join(EXT_DIR, 'hashmap'),
                path.join(EXT_DIR, 'tpl', 'src'),
                path.join(EXT_DIR, 'log', 'src'),
            ],
            libraries=['uuid'],
            extra_compile_args=compile_args,
        ),
    ],
)
